从零开始学Java 您所在的位置:网站首页 opengl 底层调用 从零开始学Java

从零开始学Java

2023-04-18 03:58| 来源: 网络整理| 查看: 265

在之前的两篇文章中,给大家介绍了Java中的包装类及其特点、用法(从零开始学Java—包装类的装箱与拆箱问题),但是这些内容主要是停留在”怎么用“的层面,没有太多涉及”为什么“,所以接下来会给大家讲一讲Integer这个包装类的底层原理。在现在的就业环境下,我们需要知其然,还要知其所以然,才能更好地满足就业需求。

一. Integer底层原理探究1. int和Integer的区别

在前面的内容介绍中,给大家讲过Integer这个类,现在大家对它的用法应该都比较清楚了。但是除了要掌握Integer的用法之外,我们还要了解它的一些底层内容,因为在面试时,关于Integer的底层考察的比较多。比如一个常见的面试题是这样的:请问int和Integer的区别有哪些?

面对这样的一道题目,你该怎么回答?常规的答案其实很容易答出来,比如:

int是基本数据类型,代表整型数据,默认值是0;Integer是 int的包装类,属于引用类型,默认值为null;int 和 Integer 都可以表示某一个整型数值;Integer变量实际是对象的引用,当new一个Integer时,实际上是生成一个指针指向此对象;而int则是直接存储数据值;Integer可以区分出未赋值和值为 0 的区别,而int 则无法表达出未赋值的情况;int 和 Integer 不能够互用,因为他们是两种不同的数据类型;int在初始化时,可以直接写成 int=1 的形式;因为Integer是包装类型,使用时可以采用 Integer i = new Integer(1) 的形式,但因为Java中的自动装箱和拆箱机制,使得对Integer类的赋值也可以使用 Integer i= 1 的形式;如果我们只是进行一些加减乘除的运算 或者 作为参数进行传递,那么就可以直接使用int这样的基本数据类型;但如果想按照对象来进行操作处理,那么就要使用Integer来声明一个对象。

但是如果你只能回答出这样的答案,你在面试官的眼里只能算合格,还算不上优秀,我们需要对Integer了解地更多一些。

2. 被final修饰的Integer类

为了搞清楚Integer的底层,我们就不得不研究一下它的源码,我们来追踪一下Integer源码,如下图所示:

从源码中可以看出,Integer是Number的一个子类,且被final所修饰!请大家回顾一些之前讲过的final知识点。我们知道,被final修饰的类是常量类,该类不能被继承,里面的方法不能被重写,创建出的对象也不能被修改!总之,Integer符合final类的特征。

3. IntegerCache缓冲区

我们还记得,在Integer中有一个valueOf()方法,该方法可以将int值转为Integer对象。接下来我们来看看该方法的实现源码,如下图所示:

从上图的源码截图中我们可以看到,Integer中有一个缓冲区叫做IntegerCache,这是Integer中的一个内部类,如下图所示:

我们可以看到,low就是-128,high等于127,这是缓冲区的最低和最高边界。那么这个缓冲区的存在到底有什么用呢?大家别着急,我们先做几个核心实验。

4. 几个核心实验

为了能够讲清楚Integer的底层逻辑,给大家设计了如下代码,用于验证Integer的底层设计。

4.1 比较new出的两个Integer对象

我们通过new对象的方式,来创建两个Integer对象i和j,并比较这两个对象。

//通过new生成的两个Integer变量进行比较,结果为false Integer i = new Integer(100); Integer j = new Integer(100); System.out.print(i == j); //false

从运行的结果中可以看出,通过new生成的两个Integer对象永远是不会相等的。这是因为new生成的是两个对象,Integer变量实际上是对Integer对象的引用,这两个对象的内存地址是不同的。

4.2 Integer对象和int变量进行比较

接下来我们在把一个Integer对象和int变量进行比较,如下:

Integer i = new Integer(100); int j = 100; System.out.print(i == j); //true

Integer变量和int变量进行比较时,只要两个变量的值是相等的,结果就为true。这是因为Integer包装类和int基本类型进行比较时,Java会进行自动拆箱操作,将Integer转为了int,然后再进行比较,实际上就变为了两个int变量的比较。本案例中两者的值都是100,所以用“==”等号进行比较时自然就是相等的。

4.3 非new的Integer变量和new出的Integer变量进行比较

然后我们再把一个非new的Integer变量和new出的Integer变量进行比较,如下所示:

//非new生成的Integer变量和new Integer()生成的变量进行比较 Integer i = new Integer(100); //自动装箱 Integer j = 100; System.out.print(i == j); //false

在这段代码中,非new生成的Integer变量和new Integer()生成的变量进行比较时,结果却为false!这是因为非new生成Integer变量时,内部会调用valueOf()方法,进行自动装箱操作,此时会把Integer变量的值指向Java常量池中的数据。而new Integer()生成的变量,则指向的是堆中新建的对象,两者在内存中的地址是不同的。

4.4 两个非new生成的Integer对象进行比较

接着我们再对两个非new生成的Integer对象进行比较,如下所示:

//两个非new生成的Integer对象进行比较 //i与j的取值范围是在 -128~127 之间! Integer i = 100; Integer j = 100; System.out.print(i == j); //true //x与y的取值范围不在 -128~127 之间! Integer x = 200; Integer y = 200; System.out.print(x == y); //false

这段代码中,两个非new生成的Integer对象进行比较时,如果两个变量的取值在 -128到127 之间,则比较结果为true;如果两个变量的值不在此区间,则比较结果为false。这又是为什么呢? 其实要想弄明白这个原因,我们只需要看看Integer类的valueOf()方法是怎么写的就可以了。valueOf()方法源码如下:

public static Integer valueOf(int i) { if (i >= IntegerCache.low && i


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有